<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>xmake</title>
  <link rel="icon" href="/assets/img/favicon.ico">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta name="description" content="Description">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <link href="//cdn.jsdelivr.net/npm/github-markdown-css@4.0.0/github-markdown.min.css" rel="stylesheet">
  <style>
	.markdown-body {
		box-sizing: border-box;
		min-width: 200px;
		max-width: 980px;
		margin: 0 auto;
		padding: 45px;
	}

	@media (max-width: 767px) {
		.markdown-body {
			padding: 15px;
		}
	}
  </style>
</head>
<body>
<article class="markdown-body">
<h4>This is a mirror page, please see the original page: </h4><a href="https://xmake.io/#/zh-cn/manual/custom_toolchain">https://xmake.io/#/zh-cn/manual/custom_toolchain</a>
</br>
    <script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7I52QU&placement=xmakeio" id="_carbonads_js"></script>
<style>
#carbonads {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu,
  Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
}

#carbonads {
  display: flex;
  max-width: 330px;
  background-color: hsl(0, 0%, 98%);
  box-shadow: 0 1px 4px 1px hsla(0, 0%, 0%, .1);
}

#carbonads a {
  color: inherit;
  text-decoration: none;
}

#carbonads a:hover {
  color: inherit;
}

#carbonads span {
  position: relative;
  display: block;
  overflow: hidden;
}

#carbonads .carbon-wrap {
  display: flex;
}

.carbon-img {
  display: block;
  margin: 0;
  line-height: 1;
}

.carbon-img img {
  display: block;
}

.carbon-text {
  font-size: 13px;
  padding: 10px;
  line-height: 1.5;
  text-align: left;
}

.carbon-poweredby {
  display: block;
  padding: 8px 10px;
  background: repeating-linear-gradient(-45deg, transparent, transparent 5px, hsla(0, 0%, 0%, .025) 5px, hsla(0, 0%, 0%, .025) 10px) hsla(203, 11%, 95%, .4);
  text-align: center;
  text-transform: uppercase;
  letter-spacing: .5px;
  font-weight: 600;
  font-size: 9px;
  line-height: 1;
}
</style>
    <p>在2.3.4版本之后，xmake已经支持在用户的项目xmake.lua中自定义工具链，例如：</p>
<pre><code class="lang-lua">-- define toolchain
toolchain("myclang")

    -- mark as standalone toolchain
    set_kind("standalone")

    -- set toolset
    set_toolset("cc", "clang")
    set_toolset("cxx", "clang", "clang++")
    set_toolset("ld", "clang++", "clang")
    set_toolset("sh", "clang++", "clang")
    set_toolset("ar", "ar")
    set_toolset("ex", "ar")
    set_toolset("strip", "strip")
    set_toolset("mm", "clang")
    set_toolset("mxx", "clang", "clang++")
    set_toolset("as", "clang")

    add_defines("MYCLANG")

    -- check toolchain
    on_check(function (toolchain)
        return import("lib.detect.find_tool")("clang")
    end)

    -- on load
    on_load(function (toolchain)

        -- get march
        local march = is_arch("x86_64", "x64") and "-m64" or "-m32"

        -- init flags for c/c++
        toolchain:add("cxflags", march)
        toolchain:add("ldflags", march)
        toolchain:add("shflags", march)
        if not is_plat("windows") and os.isdir("/usr") then
            for _, includedir in ipairs({"/usr/local/include", "/usr/include"}) do
                if os.isdir(includedir) then
                    toolchain:add("includedirs", includedir)
                end
            end
            for _, linkdir in ipairs({"/usr/local/lib", "/usr/lib"}) do
                if os.isdir(linkdir) then
                    toolchain:add("linkdirs", linkdir)
                end
            end
        end

        -- init flags for objc/c++  (with ldflags and shflags)
        toolchain:add("mxflags", march)

        -- init flags for asm
        toolchain:add("asflags", march)
    end)
</code></pre>
<p>然后通过下面的命令切到自己定义的工具链就行了：</p>
<pre><code class="lang-bash">$ xmake f --toolchain=myclang
</code></pre>
<p>当然，我们也可以通过<code>set_toolchains</code>接口直接对指定target切换设置到自定义工具链。</p>
<p>在自定义工具前，我们可以通过先运行以下命令，查看完整的内置工具链列表，确保xmake没有提供，如果有的话，直接使用就行了，没必要自己定义：</p>
<pre><code class="lang-bash">$ xmake show -l toolchains
</code></pre>
<p>下面是自定义toolchain目前支持的接口列表：</p>
<table>
<thead>
<tr>
<th>接口</th>
<th>描述</th>
<th>支持版本</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#toolchain">toolchain</a></td>
<td>定义工具链</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="#toolchainset_kind">set_kind</a></td>
<td>设置工具链类型</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="#toolchainset_toolset">set_toolset</a></td>
<td>设置工具集</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="#toolchainset_sdkdir">set_sdkdir</a></td>
<td>设置工具链sdk目录路径</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="#toolchainset_bindir">set_bindir</a></td>
<td>设置工具链bin目录路径</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="#toolchainon_check">on_check</a></td>
<td>检测工具链</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="#toolchainonon_load">on_load</a></td>
<td>加载工具链</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="#toolchain_end">toolchain_end</a></td>
<td>结束定义工具链</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_includedirs">add_includedirs</a></td>
<td>添加头文件搜索目录</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_defines">add_defines</a></td>
<td>添加宏定义</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_undefines">add_undefines</a></td>
<td>取消宏定义</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_cflags">add_cflags</a></td>
<td>添加c编译选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_cxflags">add_cxflags</a></td>
<td>添加c/c++编译选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_cxxflags">add_cxxflags</a></td>
<td>添加c++编译选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_mflags">add_mflags</a></td>
<td>添加objc编译选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_mxflags">add_mxflags</a></td>
<td>添加objc/objc++编译选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_mxxflags">add_mxxflags</a></td>
<td>添加objc++编译选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_scflags">add_scflags</a></td>
<td>添加swift编译选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_asflags">add_asflags</a></td>
<td>添加汇编编译选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_gcflags">add_gcflags</a></td>
<td>添加go编译选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_dcflags">add_dcflags</a></td>
<td>添加dlang编译选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_rcflags">add_rcflags</a></td>
<td>添加rust编译选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_cuflags">add_cuflags</a></td>
<td>添加cuda编译选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_culdflags">add_culdflags</a></td>
<td>添加cuda设备链接选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_ldflags">add_ldflags</a></td>
<td>添加链接选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_arflags">add_arflags</a></td>
<td>添加静态库归档选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_shflags">add_shflags</a></td>
<td>添加动态库链接选项</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_languages">add_languages</a></td>
<td>添加语言标准</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_frameworks">add_frameworks</a></td>
<td>添加链接框架</td>
<td>>= 2.3.4</td>
</tr>
<tr>
<td><a href="/mirror/zh-cn/manual/project_target.html#targetadd_frameworkdirs">add_frameworkdirs</a></td>
<td>添加链接框架</td>
<td>>= 2.3.4</td>
</tr>
</tbody>
</table>
<h3 id="toolchain">toolchain</h3>
<h4 id="">定义工具链</h4>
<p>可以在用户项目xmake.lua中定义，也可以通过includes独立到单独的xmake.lua去专门定义各种工具链</p>
<pre><code class="lang-lua">toolchain("myclang")
    set_toolset("cc", "clang")
    set_toolset("cxx", "clang", "clang++")
toolchain_end()
</code></pre>
<h4 id="">定义交叉工具链</h4>
<p>我们也可以在 xmake.lua 中针对不同的交叉工具链sdk进行自定义配置，通常只需要指定 sdkdir，xmake就可以自动检测其他的配置，比如 cross 等信息，例如:</p>
<pre><code class="lang-lua">toolchain("my_toolchain")
    set_kind("standalone")
    set_sdkdir("/tmp/arm-linux-musleabi-cross")
toolchain_end()

target("hello")
    set_kind("binary")
    add_files("apps/hello/*.c")
</code></pre>
<p>这是一个最精简的交叉工具链配置，仅仅设置了对应的sdk路径，然后通过 <code>set_kind("standalone")</code> 将其标记为完整独立的工具链。</p>
<p>这个时候，我们就可以通过命令行 <code>--toolchain=my_toolchain</code> 去手动切换到此工具链来使用。</p>
<pre><code class="lang-console">xmake f --toolchain=my_toolchain
xmake
</code></pre>
<p>另外，我们还可以直接在 xmake.lua 中通过 <code>set_toolchains</code> 将其绑定到对应的 target 上去，那么仅仅只在编译此 target 时候，才会切换到我们自定义的工具链。</p>
<pre><code class="lang-lua">toolchain("my_toolchain")
    set_kind("standalone")
    set_sdkdir("/tmp/arm-linux-musleabi-cross")
toolchain_end()

target("hello")
    set_kind("binary")
    add_files("apps/hello/*.c")
    set_toolchains("my_toolchain")
</code></pre>
<p>这样，我们不再需要手动切换工具链了，只需要执行 xmake，就会默认自动切换到 my_toolchain 工具链。</p>
<p>这对于嵌入式开发来讲尤其有用，因为嵌入式平台的交叉编译工具链非常多，我们经常需要各种切换来完成不同平台的编译。</p>
<p>因此，我们可以将所有的工具链定义放置到独立的 lua 文件中去定义，例如：</p>
<pre><code>projectdir
    - xmake.lua
    - toolchains
      - my_toolchain1.lua
      - my_toolchain2.lua
      - ...
</code></pre><p>然后，我们只需要再 xmake.lua 中通过 includes 去引入它们，并根据不同的自定义平台，绑定不同的工具链：</p>
<pre><code class="lang-lua">includes("toolchains/*.lua")
target("hello")
    set_kind("binary")
    add_files("apps/hello/*.c")
    if is_plat("myplat1") then
        set_toolchains("my_toolchain1")
    elseif is_plat("myplat2") then
        set_toolchains("my_toolchain2")
    end
</code></pre>
<p>这样，我们就可以编译的时候，直接快速切换指定平台，来自动切换对应的工具链了。</p>
<pre><code class="lang-console">xmake f -p myplat1
xmake
</code></pre>
<p>如果，有些交叉编译工具链结构复杂，自动检测还不足够，那么可以根据实际情况，使用 <code>set_toolset</code>, <code>set_cross</code> 和 <code>set_bindir</code> 等接口，针对性的配置上其他的设置。</p>
<p>例如下面的例子，我们还额外添加了一些 cxflags/ldflags 以及内置的系统库 links。</p>
<pre><code class="lang-lua">toolchain("my_toolchain")
    set_kind("standalone")
    set_sdkdir("/tmp/arm-linux-musleabi-cross")
    on_load(function (toolchain)
        -- add flags for arch
        if toolchain:is_arch("arm") then
            toolchain:add("cxflags", "-march=armv7-a", "-msoft-float", {force = true})
            toolchain:add("ldflags", "-march=armv7-a", "-msoft-float", {force = true})
        end
        toolchain:add("ldflags", "--static", {force = true})
        toolchain:add("syslinks", "gcc", "c")
    end)
</code></pre>
<p>更多自定义工具链的例子，我们可以看下面的接口文档，也可以到 xmake 的源码的目录参考内置的工具链定义：<a href="https://github.com/xmake-io/xmake/blob/master/xmake/toolchains/">内部工具链列表</a></p>
<h3 id="toolchainset_kind">toolchain:set_kind</h3>
<h4 id="">设置工具链类型</h4>
<p>目前仅支持设置为<code>standalone</code>类型，表示当前工具链是独立完整的工具链，包括cc/cxx/ld/sh/ar等编译器、归档器、链接器等一整套工具集的配置。</p>
<p>通常用于某个target被同时设置了多个工具链的情况，但同时只能生效一个独立工具链，通过此配置可以保证生效的工具链存在互斥关系，比如gcc/clang工具链不会同时生效。</p>
<p>而像yasm/nasm这种局部工具链，属于附加的局部工具链扩展，不用设置standalone，因为clang/yasm两个工具链有可能同时存在。</p>
<p>!> 只要记住，存在完整编译环境的工具链，都设置为standalone就行了</p>
<h3 id="toolchainset_toolset">toolchain:set_toolset</h3>
<h4 id="">设置工具集</h4>
<p>用于设置每个单独工具名和路径，例如：</p>
<pre><code class="lang-lua">toolchain("myclang")
    set_kind("standalone")
    set_toolset("cc", "clang")
    set_toolset("cxx", "clang", "clang++")
    set_toolset("ld", "clang++", "clang")
    set_toolset("sh", "clang++", "clang")
    set_toolset("ar", "ar")
    set_toolset("ex", "ar")
    set_toolset("strip", "strip")
    set_toolset("mm", "clang")
    set_toolset("mxx", "clang", "clang++")
    set_toolset("as", "clang")
</code></pre>
<p>关于这个接口的详情，可以看下：<a href="/mirror/zh-cn/manual/project_target.html#targetset_toolset">target.set_toolset</a></p>
<h3 id="toolchainset_sdkdir">toolchain:set_sdkdir</h3>
<h4 id="sdk">设置工具链sdk目录路径</h4>
<p>通常我们可以通过<code>xmake f --toolchain=myclang --sdk=xxx</code>来配置sdk目录，但是每次配置比较繁琐，我们也可以通过此接口预先配置到xmake.lua中去，方便快速切换使用。</p>
<pre><code class="lang-lua">toolchain("myclang")
    set_kind("standalone")
    set_sdkdir("/tmp/sdkdir")
    set_toolset("cc", "clang")
</code></pre>
<h3 id="toolchainset_bindir">toolchain:set_bindir</h3>
<h4 id="bin">设置工具链bin目录路径</h4>
<p>通常我们可以通过<code>xmake f --toolchain=myclang --bin=xxx</code>来配置sdk目录，但是每次配置比较繁琐，我们也可以通过此接口预先配置到xmake.lua中去，方便快速切换使用。</p>
<pre><code class="lang-lua">toolchain("myclang")
    set_kind("standalone")
    set_bindir("/tmp/sdkdir/bin")
    set_toolset("cc", "clang")
</code></pre>
<h3 id="toolchainon_check">toolchain:on_check</h3>
<h4 id="">检测工具链</h4>
<p>用于检测指定工具链所在sdk或者程序在当前系统上是否存在，通常用于多个standalone工具链的情况，进行自动探测和选择有效工具链。</p>
<p>而对于<code>xmake f --toolchain=myclang</code>手动指定的场景，此检测配置不是必须的，可以省略。</p>
<pre><code class="lang-lua">toolchain("myclang")
    on_check(function (toolchain)
        return import("lib.detect.find_tool")("clang")
    end)
</code></pre>
<h3 id="toolchainon_load">toolchain:on_load</h3>
<h4 id="">加载工具链</h4>
<p>对于一些复杂的场景，我们可以在on_load中动态灵活的设置各种工具链配置，比在描述域设置更加灵活，更加强大：</p>
<pre><code class="lang-lua">toolchain("myclang")
    set_kind("standalone")
    on_load(function (toolchain)

        -- set toolset
        toolchain:set("toolset", "cc", "clang")
        toolchain:set("toolset", "ld", "clang++")

        -- init flags 
        local march = toolchain:is_arch("x86_64", "x64") and "-m64" or "-m32"
        toolchain:add("cxflags", march)
        toolchain:add("ldflags", march)
        toolchain:add("shflags", march)
    end)
</code></pre>
<h3 id="toolchain_end">toolchain_end</h3>
<h4 id="">结束定义工具链</h4>
<p>这个是可选的，如果想要手动结束toolchain的定义，可以调用它：</p>
<pre><code class="lang-lua">toolchain("myclang")
    -- ..
toolchain_end()
</code></pre>
</article>
</body>
</html>